﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HumanWorkflow.InternalDsl;
using HumanWorkflow.Framework;
using HumanWorkflow.SemanticModel;

namespace OrderWorkflow.OrderWorkflowWithInternalDsl
{
    public class OrderWorkflowWithInternalDsl : HumanWorkflowEngine
    {
        public OrderWorkflowWithInternalDsl()
            : base(CustomInitializeSemanticModel())
        {
        }

        static HumanWorkflowSemanticModel CustomInitializeSemanticModel()
        {

            HumanWorkflowSemanticModel semanticModel =
                HumanWorkflowBuilder.HumanWorkflow("OrderWorkflow")
                    .Initial("Start")
                        .GoesTo("ConcordeCustomerData")
                        .WhenEvent("Start")

                    .HumanWork("ConcordeCustomerData")
                        .DoneBy("CustomerCare")
                        .GoesTo("CheckPossibleDiscounts")
                        .WhenEvent("ConcordanceReady")

                    .HumanWork("CheckPossibleDiscounts")
                        .DoneBy("CustomerCare")
                        .GoesTo("AreAllItemsOnStock")
                        .WhenEvent("DiscountCheckReady")

                    .Decision("AreAllItemsOnStock")

                        .GoesTo("SendNotificationEmailToCustomer")
                        .WhenEvent("ItemsAreMissing")

                        .GoesTo("ShipItems")
                        .WhenEvent("ItemsAreAvailable")

                    // ItemsAreMissing thread
                    .SystemCommand("SendNotificationEmailToCustomer")
                        .GoesTo("OrderMissingItems")
                        .WhenEvent("EmailSent")

                    .HumanWork("OrderMissingItems")
                        .DoneBy("OrderHandling")
                        .GoesTo("WaitForItemsToArrive")
                        .WhenEvent("MissingItemsOrderDone")

                    .HumanWork("WaitForItemsToArrive")
                        .DoneBy("OrderHandling")
                        .GoesTo("ShipItems")
                        .WhenEvent("MissingItemsArrived")
                    
                    // ItemsAreAvailable thread
                    .HumanWork("ShipItems")
                        .DoneBy("Inventory")
                        .GoesTo("Finish")
                        .WhenEvent("ItemsShipped")

                    .Final("Finish")

                    .End();

            AddStopEventToAllStates(semanticModel);

            return semanticModel;
        }

        static void AddStopEventToAllStates(HumanWorkflowSemanticModel semanticModel)
        {
            FinalStep finalStep = (FinalStep)((IList<Step>)semanticModel.Steps).Where<Step>(s => s is FinalStep).First<Step>();

            foreach (Step step in semanticModel.Steps)
            {
                if (!(step is FinalStep))
                {
                    semanticModel.AddTransition(step.Name, finalStep.Name, step.Name + "StopWorkflow");
                }

            }
        }

        public bool StocksAreOk { get; set; }

        public override string ExecuteAutomaticStep(Step executedStep)
        {
            string nextTransitionName;

            switch (executedStep.Name)
            {
                case OrderWorkflowWithFrameworkSteps.AreAllItemsOnStockDecisionStep:
                    if (StocksAreOk)
                    {
                        nextTransitionName = OrderWorkflowWithFrameworkTransitions.ItemsAreAvailable;
                    }
                    else
                    {
                        nextTransitionName = OrderWorkflowWithFrameworkTransitions.ItemsAreMissing;
                    }

                    break;
                case OrderWorkflowWithFrameworkSteps.SendNotificationEmailToCustomerAutomaticStep:

                    //TODO: send an email here to the customer

                    nextTransitionName = OrderWorkflowWithFrameworkTransitions.EmailSent;
                    break;

                default:
                    throw new NotImplementedException(executedStep.Name + " is not implemented in ExecuteAutomaticStep override.");

            }

            return nextTransitionName;
        }
    }
}
